package com.xc.hotelmgr.datapusherali.service.fz.impl;

import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.TypeReference;
import com.google.common.collect.Lists;
import com.xc.hotelmgr.datapusherali.pojo.ali.ZqDate;
import com.xc.hotelmgr.datapusherali.pojo.ali.redis.OurRatePlanPrice;
import com.xc.hotelmgr.datapusherali.pojo.ali.redis.RPAddPrice;
import com.xc.hotelmgr.datapusherali.pojo.mq.RatesCallBack;
import com.xc.hotelmgr.datapusherali.pojo.mybatis.*;
import com.xc.hotelmgr.datapusherali.service.fz.RatesService;
import com.xc.hotelmgr.datapusherali.service.mybatis.*;
import com.xc.hotelmgr.datapusherali.utils.Constant;
import com.xc.hotelmgr.datapusherali.utils.FZUtil;
import com.xc.hotelmgr.datapusherali.utils.RedisUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class RatesServiceImpl implements RatesService {
    @Autowired
    private RedisUtils redisUtils;

    @Autowired
    private OpTaskDetailService opTaskDetailService;

    /**
     * 推送价格房态
     */
    @Override
    public String hotelRatesSend(RatesCallBack ratesCallBack) throws InterruptedException {
        String appKey = ratesCallBack.getAppKey();
        String secret = ratesCallBack.getSecret();
        String sessionKey = ratesCallBack.getSessionKey();
        Long rpCode = ratesCallBack.getRpCode();

        //获取rp所属的店铺、酒店、房型
        String storeHtlRoomCode = (String) redisUtils.hashGet(Constant.RedisKey.RP_HTL_ROOM.getValue(), rpCode.toString());
        if (StringUtils.isBlank(storeHtlRoomCode)) {
            log.error("酒店信息未保存到Redis，rp：{}", rpCode);
            return "ok";
        }
        //如果酒店没有在店铺上架，则直接返回
        String[] storeHtlRoomCodes = storeHtlRoomCode.split("\\|");
        String strStores = storeHtlRoomCodes[0];
        Boolean isUpStore = false;
        if(StringUtils.isBlank(strStores)){
            return  "ok";
        }
        //看该店铺是否已经上架该酒店
        String[] stores = strStores.split(",");
        for (String store : stores){
            if(store.equals(ratesCallBack.getStoreId().toString())){
                isUpStore = true;
                break;
            }
        }
        if(!isUpStore){
            return  "ok";
        }

        Long hotelId = Long.valueOf(storeHtlRoomCodes[1]);
        Long roomCode = Long.valueOf(storeHtlRoomCodes[2]);

        //获取自定义价格计划
        List<OpOurRateplan> opOurRateplans = Lists.newArrayList();
        List<String> ourPlanIds = Lists.newArrayList();
        String key = Constant.RedisKey.STORE_HTL_USE_OURPLAN.getValue() + ratesCallBack.getAppKey();
        String strOurPlans = (String) redisUtils.hashGet(key, hotelId.toString());

        //如果有自定义价格政策
        if (StringUtils.isNotBlank(strOurPlans)) {
            String[] ourPlans = strOurPlans.split(",");
            for (String ourPlan : ourPlans) {
                OpOurRateplan opOurRateplan = new OpOurRateplan();
                opOurRateplan.setId(Integer.valueOf(ourPlan));
                opOurRateplans.add(opOurRateplan);
                //后面取自定义价格政策加价配置使用
                ourPlanIds.add(ourPlan);
            }
        } else {
            //如果没有配置自定义价格政策，默认添加一个id=0的自定义价格政策
            opOurRateplans.add(new OpOurRateplan());
        }
        //获取rp加价配置
        //酒店加价配置
        List<OpHtlPrice> opHtlPrices = Lists.newArrayList();
        //自定义价格计划加价配置
        List<OurRatePlanPrice> ourRateplanPrices = Lists.newArrayList();
        //通用加价配置
        List<OpCommPrice> opCommPrices = Lists.newArrayList();

        key = Constant.RedisKey.STORE_RP_USE_ADD_PRICE.getValue() + ratesCallBack.getAppKey();
        String rpUseAddPrice = (String) redisUtils.hashGet(key, rpCode.toString());
        //如果配置了加价配置
        RPAddPrice rPAddPrice = null;
        if (StringUtils.isNotBlank(rpUseAddPrice)) {
            rPAddPrice = FZUtil.parseRpUseAddPrice(rpUseAddPrice);
            switch (rPAddPrice.getStoreRPUseAddPrice()) {
                case HTL:
                    key = Constant.RedisKey.STORE_HTL_ADD_PRICE.getValue() + ratesCallBack.getAppKey();
                    String strOpHtlPrices = redisUtils.hashGet(key, hotelId.toString()).toString();
                    opHtlPrices = JSONObject.parseObject(strOpHtlPrices, new TypeReference<List<OpHtlPrice>>() {
                    });
                    break;
                case OURPLAN:
                    //通过自定义价格政策ID，获取自定义价格政策加价配置
                    key = Constant.RedisKey.STORE_CFG_CUSTOM_OURPLAN.getValue() + ratesCallBack.getAppKey();
                    List<Object> ourPlanPriceObjs = redisUtils.hashGetAll(key, ourPlanIds);
                    for (Object ourPlanPriceObj : ourPlanPriceObjs) {
                        List<OurRatePlanPrice> temp = JSONObject.parseObject(ourPlanPriceObj.toString(), new TypeReference<List<OurRatePlanPrice>>() {
                        });
                        ourRateplanPrices.addAll(temp);
                    }
                    break;
                case COMM:
                    //通过自定义价格政策ID，获取自定义价格政策加价配置
                    key = Constant.RedisKey.STORE_USE_ADD_PRICE.getValue() + ratesCallBack.getAppKey();
                    String strOpCommPrices = redisUtils.get(key);
                    opCommPrices = JSONObject.parseObject(strOpCommPrices, new TypeReference<List<OpCommPrice>>() {
                    });
                    break;
            }
        }
        //获取停售日期设置
        ZqDate zqDate = redisUtils.get(ratesCallBack.getAppKey(), ZqDate.class);
        List<String> dateList = Lists.newArrayList();
        if (zqDate != null && zqDate.getDateList() != null) {
            dateList = zqDate.getDateList();
        }

        //获取RPS
        List<HtDailyRoom> htDailyRooms = Lists.newArrayList();
        List<String> priceDates = ratesCallBack.getDates();
        Integer retryCnt = 0;
        boolean retrySuccess = false;
        try{
            htDailyRooms = redisUtils.getRpsByPipeline(priceDates,rpCode);
            retrySuccess = true;
        }catch (Exception ex){
            retrySuccess = false;
        }
        while (!retrySuccess && retryCnt < Constant.TRYCNT){
            Thread.sleep(Constant.SLEEP_TIME);
            retryCnt++;
            try{
                htDailyRooms = redisUtils.getRpsByPipeline(priceDates,rpCode);
                retrySuccess = true;
            }catch (Exception ex){
                retrySuccess = false;
            }
        }
        //开始推送
        for (OpOurRateplan opOurRateplan : opOurRateplans) {
            String newRpCodeStr = String.valueOf(rpCode);
            Integer opOurRatePlanId = opOurRateplan.getId();
            String rpCodeStr = String.valueOf(rpCode);
            //自定义价格政策加价配置
            List<OurRatePlanPrice> thisOurRatePlanPrices = Lists.newArrayList();
            if (opOurRatePlanId != 0) {
                newRpCodeStr = rpCodeStr + "XC" + opOurRatePlanId;
                //如果配置了自定义加价配置
                if (rPAddPrice != null && rPAddPrice.getStoreRPUseAddPrice().equals(Constant.StoreRPUseAddPrice.OURPLAN)) {
                    //获取本自定义价格政策加价配置
                    thisOurRatePlanPrices = ourRateplanPrices.stream().filter((item) -> {
                        return item.getOurRpId().equals(opOurRatePlanId);
                    }).collect(Collectors.toList());
                }
                if(thisOurRatePlanPrices == null){
                    log.info("自定义价格政策未配置加价，appkey{}，酒店id：{}，房型id：{}，rp：{}，自定义价格计划id：{}",appKey,hotelId,roomCode,rpCode,opOurRatePlanId);
                    log.info("自定义价格政策未配置加价，strOurPlans：{}，opOurRateplans{}",strOurPlans,opOurRateplans);
                    return "ok";
                }
            }
            for (HtDailyRoom htDailyRoom : htDailyRooms) {
                //停售日期设置
                if (dateList.contains(htDailyRoom.getPriceDate())) {
                    htDailyRoom.setSaleNum(0);
                }
                //计算价格
                int newPrice = FZUtil.calcSendRPSPrice(opCommPrices, opHtlPrices, thisOurRatePlanPrices, htDailyRoom);
                htDailyRoom.setPrice(newPrice);
            }
            String result = FZUtil.ratesSend(htDailyRooms, roomCode, newRpCodeStr, appKey, sessionKey, secret);
            //超频重试
            retryCnt = 0;
            JSONObject resultObj = JSONObject.parseObject(result);
            JSONObject errorObject =  resultObj.getJSONObject("error_response");
            if(errorObject != null && errorObject.get("sub_code") != null ){
                String subErrorCode = errorObject.get("sub_code").toString();
                while ((subErrorCode.contains("accesscontrol.limited-by-seller-api-access-count") || subErrorCode.equals("accesscontrol.limited-by-app-api-access-count")) && retryCnt < Constant.TRYCNT){
                    Thread.sleep(Constant.SLEEP_TIME);
                    result = FZUtil.ratesSend(htDailyRooms, roomCode, newRpCodeStr, appKey, sessionKey, secret);
                    resultObj = JSONObject.parseObject(result);
                    errorObject =  resultObj.getJSONObject("error_response");
                    //如果没有错误信息，则退出
                    if(errorObject == null || errorObject.get("sub_code") == null ){
                        break;
                    }
                    subErrorCode = errorObject.get("sub_code").toString();
                    retryCnt ++;
                }
            }

            if (!result.contains("xhotel_rates_increment_response")) {
                OpTaskDetail opTaskDetail = new OpTaskDetail();
                opTaskDetail.setHotelId(hotelId);
                if(ratesCallBack.getTaskId() != null){
                    opTaskDetail.setTaskId(ratesCallBack.getTaskId());
                }
                opTaskDetail.setReason(newRpCodeStr + "&" + "价格推送失败" + "&" + result);
                opTaskDetailService.insertIgnoreNull(opTaskDetail);
            } else {
                log.info("push-ps-goodsId：" + newRpCodeStr);
            }
        }
        return "ok";
    }


    /**
     * 推送价格房态
     */
    @Override
    public String zeroRatesSend(RatesCallBack ratesCallBack) throws InterruptedException {
        String appKey = ratesCallBack.getAppKey();
        String secret = ratesCallBack.getSecret();
        String sessionKey = ratesCallBack.getSessionKey();
        Long rpCode = ratesCallBack.getRpCode();

        //获取rp所属的店铺、酒店、房型
        String storeHtlRoomCode = (String) redisUtils.hashGet(Constant.RedisKey.RP_HTL_ROOM.getValue(), rpCode.toString());
        if (StringUtils.isBlank(storeHtlRoomCode)) {
            log.error("酒店信息未保存到Redis，rp：{}", rpCode);
            return "ok";
        }
        //如果酒店没有在店铺上架，则直接返回
        String[] storeHtlRoomCodes = storeHtlRoomCode.split("\\|");
        String strStores = storeHtlRoomCodes[0];
        Boolean isUpStore = false;
        if(StringUtils.isBlank(strStores)){
            return  "ok";
        }
        //看该店铺是否已经上架该酒店
        String[] stores = strStores.split(",");
        for (String store : stores){
            if(store.equals(ratesCallBack.getStoreId().toString())){
                isUpStore = true;
                break;
            }
        }
        if(!isUpStore){
            return  "ok";
        }

        Long hotelId = Long.valueOf(storeHtlRoomCodes[1]);
        Long roomCode = Long.valueOf(storeHtlRoomCodes[2]);

        //获取自定义价格计划
        List<OpOurRateplan> opOurRateplans = Lists.newArrayList();
        List<String> ourPlanIds = Lists.newArrayList();
        String key = Constant.RedisKey.STORE_HTL_USE_OURPLAN.getValue() + ratesCallBack.getAppKey();
        String strOurPlans = (String) redisUtils.hashGet(key, hotelId.toString());

        //如果有自定义价格政策
        if (StringUtils.isNotBlank(strOurPlans)) {
            String[] ourPlans = strOurPlans.split(",");
            for (String ourPlan : ourPlans) {
                OpOurRateplan opOurRateplan = new OpOurRateplan();
                opOurRateplan.setId(Integer.valueOf(ourPlan));
                opOurRateplans.add(opOurRateplan);
                //后面取自定义价格政策加价配置使用
                ourPlanIds.add(ourPlan);
            }
        } else {
            //如果没有配置自定义价格政策，默认添加一个id=0的自定义价格政策
            opOurRateplans.add(new OpOurRateplan());
        }

        //获取RPS
        List<String> priceDates = ratesCallBack.getDates();
        List<HtDailyRoom> htDailyRooms = Lists.newArrayList();
        Integer retryCnt = 0;
        boolean retrySuccess = false;
        try{
            htDailyRooms = redisUtils.getRpsByPipeline(priceDates,rpCode);
            retrySuccess = true;
        }catch (Exception ex){
            retrySuccess = false;
        }
        while (!retrySuccess && retryCnt < Constant.TRYCNT){
            Thread.sleep(Constant.SLEEP_TIME);
            retryCnt++;
            try{
                htDailyRooms = redisUtils.getRpsByPipeline(priceDates,rpCode);
                retrySuccess = true;
            }catch (Exception ex){
                retrySuccess = false;
            }
        }

        //开始推送
        for (OpOurRateplan opOurRateplan : opOurRateplans) {
            String newRpCodeStr = String.valueOf(rpCode);
            Integer opOurRatePlanId = opOurRateplan.getId();
            //自定义价格政策加价配置
            if (opOurRatePlanId != 0) {
                newRpCodeStr = newRpCodeStr + "XC" + opOurRatePlanId;
            }

            String result = FZUtil.ratesSend(htDailyRooms, roomCode, newRpCodeStr, appKey, sessionKey, secret);
            //超频重试
            retryCnt = 0;
            JSONObject resultObj = JSONObject.parseObject(result);
            JSONObject errorObject =  resultObj.getJSONObject("error_response");
            if(errorObject != null && errorObject.get("sub_code") != null ){
                String subErrorCode = errorObject.get("sub_code").toString();
                while ((subErrorCode.contains("accesscontrol.limited-by-seller-api-access-count") || subErrorCode.equals("accesscontrol.limited-by-app-api-access-count")) && retryCnt < Constant.TRYCNT){
                    Thread.sleep(Constant.SLEEP_TIME);
                    result = FZUtil.ratesSend(htDailyRooms, roomCode, newRpCodeStr, appKey, sessionKey, secret);
                    resultObj = JSONObject.parseObject(result);
                    errorObject =  resultObj.getJSONObject("error_response");
                    //如果没有错误信息，则退出
                    if(errorObject == null || errorObject.get("sub_code") == null ){
                        break;
                    }
                    subErrorCode = errorObject.get("sub_code").toString();
                    retryCnt ++;
                }
            }

            if (!result.contains("xhotel_rates_increment_response")) {
                OpTaskDetail opTaskDetail = new OpTaskDetail();
                opTaskDetail.setHotelId(hotelId);
                if(ratesCallBack.getTaskId() != null){
                    opTaskDetail.setTaskId(ratesCallBack.getTaskId());
                }
                opTaskDetail.setReason(newRpCodeStr + "&" + "价格推送失败" + "&" + result);
                opTaskDetailService.insertIgnoreNull(opTaskDetail);
            } else {
                log.info("push-ps-goodsId：" + newRpCodeStr);
            }
        }
        return "ok";
    }
}
